/* ***** BEGIN LICENSE BLOCK *****
   Version: Apache 2.0/GPL 3.0/LGPL 3.0

   CCT - Computational Chemistry Tools
   JMolEditor - Java Molecules Editor

   Copyright 2008 Dr. Vladislav Vasilyev

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

   Contributor(s):
     Dr. Vladislav Vasilyev <vvv900@gmail.com>       (original author)

  Alternatively, the contents of this file may be used under the terms of
  either the GNU General Public License Version 2 or later (the "GPL"), or
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  in which case the provisions of the GPL or the LGPL are applicable instead
  of those above. If you wish to allow use of your version of this file only
  under the terms of either the GPL or the LGPL, and not to allow others to
  use your version of this file under the terms of the Apache 2.0, indicate your
  decision by deleting the provisions above and replace them with the notice
  and other provisions required by the GPL or the LGPL. If you do not delete
  the provisions above, a recipient may use your version of this file under
  the terms of any one of the Apache 2.0, the GPL or the LGPL.

 ***** END LICENSE BLOCK *****/

package cct.modelling;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cct.interfaces.AtomInterface;
import cct.interfaces.BondInterface;
import cct.vecmath.vPoint3f;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2004</p>
 *
 * <p>Company: </p>
 *
 * @author not attributable
 * @version 1.0
 */
public class vAtom
    extends vPoint3f implements AtomInterface {
  protected int element;
  protected float mass;
  protected String name = "";
  protected int monomer_id = 0;
  protected boolean selected = false;
  protected boolean dynamic = true; // Whether it's allowed to be optimized
  protected Map properties = new HashMap();
  protected List bondedToAtoms = new ArrayList();
  protected List bondsIndex = new ArrayList();

  public vAtom() {
    super();
    element = -1;
  }

  public vAtom(vAtom atom) {
    super();
    element = atom.getAtomicNumber();
    name = atom.getName();
    monomer_id = atom.getSubstructureNumber();
    selected = atom.isSelected();
    dynamic = atom.isDynamic();
    x = atom.getX();
    y = atom.getY();
    z = atom.getZ();
    properties.putAll(atom.getProperties());
  }

  public vAtom(AtomInterface atom) {
    super();
    element = atom.getAtomicNumber();
    name = atom.getName();
    monomer_id = atom.getSubstructureNumber();
    selected = atom.isSelected();
    dynamic = atom.isDynamic();
    x = atom.getX();
    y = atom.getY();
    z = atom.getZ();
    properties.putAll(atom.getProperties());
  }

  public vAtom(int el) {
    super();
    element = el;
  }

  public vAtom(int el, String aName) {
    super();
    element = el;
    name = aName;
  }

  @Override
  public AtomInterface getNewAtomInstance() {
    return new vAtom();
  }

  @Override
  public AtomInterface getNewAtomInstance(AtomInterface a) {
    return new vAtom(a);
  }

  @Override
  public float getAtomicMass() {
    return mass;
  }

  @Override
  public void setAtomicMass(float mass) {
    this.mass = mass;
  }

  @Override
  public void setProperty(Object prop, Object value) {
    if (value == null) {
      properties.remove(prop);
      return;
    }
    properties.put(prop, value);
  }

  @Override
  public Object getProperty(String key) {
    return properties.get(key);
  }

  @Override
  public Map getProperties() {
    return properties;
  }

  @Override
  public int getAtomicNumber() {
    return element;
  }

  @Override
  public void setAtomicNumber(int anumber) {
    element = anumber;
  }

  @Override
  public String getName() {
    //return (String) properties.get(AtomProperties.NAME);
    return name;
  }

  @Override
  public void setName(String aName) {
    //if (name != null) {
    //properties.put(AtomProperties.NAME, name);
    //}
    this.name = aName;
  }

  @Override
  public void setSubstructureNumber(int n) {
    monomer_id = n;
  }

  @Override
  public void setSelected(boolean select) {
    selected = select;
  }

  @Override
  public int getSubstructureNumber() {
    return monomer_id;
  }

  public float distanceTo(vPoint3f a) {
    float x = this.x - a.x;
    float y = this.y - a.y;
    float z = this.z - a.z;
    return (float) Math.sqrt( (x * x + y * y + z * z));
  }

  public float distanceTo(AtomInterface a) {
    float x = this.x - a.getX();
    float y = this.y - a.getY();
    float z = this.z - a.getZ();
    return (float) Math.sqrt( (x * x + y * y + z * z));
  }

  @Override
  public List getBondedToAtoms() {
    return bondedToAtoms;
  }

  @Override
  public int getNumberOfBondedAtoms() {
    return bondedToAtoms.size();
  }

  /**
   * Used internally !!!
   * @param bond BondInterface
   * @return BondInterface
   */
  @Override
  public boolean removeBond(BondInterface bond) {
    if (!bondsIndex.contains(bond)) {
      return false;
    }
    return bondsIndex.remove(bond);
  }

  @Override
  public List getBondIndex() {
    return bondsIndex;
  }

  @Override
  public BondInterface getBondToAtom(AtomInterface a) {
    if (!bondedToAtoms.contains(a)) {
      return null; // not bonded to it
    }
    try {
      return (BondInterface) bondsIndex.get(bondedToAtoms.indexOf(a));
    }
    catch (IndexOutOfBoundsException e) {
      System.err.println("getBondtoAtom: IndexOutOfBoundsException: " + e.getMessage());
      return null;
    }
  }

  public void setBondedTo(AtomInterface a) {
    bondedToAtoms.add(a);
  }

  // !!! Function to delete !!!
  @Override
  public void setBondedTo(AtomInterface a, boolean set_bond) {
    if (set_bond) {
      if (!bondedToAtoms.contains(a)) {
        bondedToAtoms.add(a);
      }
    }
    else {
      if (!bondedToAtoms.contains(a)) {
        return;
      }
      int index = bondedToAtoms.indexOf(a);
      bondedToAtoms.remove(index);
      bondsIndex.remove(index);
    }
  }

  public void setUnbondedTo(AtomInterface a) {
    if (!bondedToAtoms.contains(a)) {
      return;
    }
    int index = bondedToAtoms.indexOf(a);
    bondedToAtoms.remove(index);
    bondsIndex.remove(index);
  }

  @Override
  public void setBondIndex(BondInterface a) {
    bondsIndex.add(a);
  }

  @Override
  public boolean isSelected() {
    return selected;
  }

  @Override
  public boolean isDynamic() {
    return dynamic;
  }

  @Override
  public vAtom clone() {
    return new vAtom(this);
  }

  @Override
  public boolean isBondedTo(AtomInterface a) {
    if (bondedToAtoms.contains(a)) {
      return true;
    }
    return false;
  }

}
